#!/bin/bash
#
# Copyright 2015-2017 Adrian DC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

# === Repo References Variables ===
export ANDROID_DEVELOPMENT_SHELL_TOOLS_REFERENCED_AOSP='8960 8996';
export ANDROID_DEVELOPMENT_SHELL_TOOLS_REFERENCED_LINEAGE='8960 8996 sodp';

# === Repo Referenced AOSP Devices ===
function reporeferencedaosp()
{
  # Usage
  if [ -z "${1}" ]; then
    echo '';
    echo ' Usage: reporeferencedaosp <"command_to_run"> <"device1 device2 ..."> (AOSP referenced repo commands launcher)';
    echo '';
    return;
  fi;

  # Variables
  local repocommon;
  local command_to_run=${1};
  local referenced_devices=${2:-${ANDROID_DEVELOPMENT_SHELL_TOOLS_REFERENCED_AOSP}};

  # Execute on common repo
  cdaosp;
  source ./build/envsetup.sh;
  repocommon=$(pwd);
  ${command_to_run};

  # Walk through devices
  for device in ${referenced_devices}; do

    # Select and verify the path existence
    cdaosp "${device}";
    if [ ! "$(pwd)" = "${repocommon}" ]; then

      # Execute on device repo
      source ./build/envsetup.sh;
      ${command_to_run};

    fi;

  done;
}

# === Repo Referenced LineageOS Devices ===
function reporeferencedlineage()
{
  # Usage
  if [ -z "${1}" ]; then
    echo '';
    echo ' Usage: reporeferencedlineage <"command_to_run"> <"device1 device2 ..."> (LineageOS referenced repo commands launcher)';
    echo '';
    return;
  fi;

  # Variables
  local repocommon;
  local command_to_run=${1};
  local referenced_devices=${2:-${ANDROID_DEVELOPMENT_SHELL_TOOLS_REFERENCED_LINEAGE}};

  # Execute on common repo
  cdlineage;
  source ./build/envsetup.sh;
  repocommon=$(pwd);
  ${command_to_run};

  # Walk through devices
  for device in ${referenced_devices}; do

    # Select and verify the path existence
    cdlineage "${device}";
    if [ ! "$(pwd)" = "${repocommon}" ]; then

      # Execute on device repo
      source ./build/envsetup.sh;
      ${command_to_run};

    fi;

  done;
}

# === Repo References Updater ===
function reporefupdate()
{
  # Usage: reporefupdate [bool_automated] (Upload new projects manifests)

  # Variables
  local current_dir;
  local params;

  # Path backup
  current_dir=$(pwd);

  # Prepare git add parameters
  if [ ! -z "${1}" ]; then
    params='-Av';
  else
    params='-Ap';
  fi;

  # Detect and update AOSP references
  for project in sony8960_n sony8960_o sony8960_o_mr1 sony8960_master sonysodp aospcaf; do
    if cddevaosp "${project}" && git submodule update --init --remote &&
        git reset "$(git rev-list --max-parents=0 --abbrev-commit HEAD)" &&
        git add -N ./ && ! git diff-index --quiet HEAD --; then
      echo '';
      echo " Updating AOSP ${project} references...";
      git add "${params}";
      if ! git diff --cached --quiet; then
        git commit --amend --no-edit;
        gitpu origin local_manifests y;
      fi;
    fi;
  done;

  # Detect and update LineageOS references
  for project in sony8960 sony8960_master sony8996 sonysodp; do
    if cddevlineage "${project}" && git submodule update --init --remote &&
        git reset "$(git rev-list --max-parents=0 --abbrev-commit HEAD)" &&
        git add -N ./ && ! git diff-index --quiet HEAD --; then
      echo '';
      echo " Updating LineageOS ${project} references...";
      git add "${params}";
      if ! git diff --cached --quiet; then
        git commit --amend --no-edit;
        gitpu origin local_manifests y;
      fi;
    fi;
  done;

  # Detect and update common manifests references
  if cddev 'android_development_manifests' && git submodule update --init --remote &&
      git reset "$(git rev-list --max-parents=0 --abbrev-commit HEAD)" &&
      git add -N ./ && ! git diff-index --quiet HEAD --; then
    echo '';
    echo " Updating common manifests references...";
    git add "${params}";
    if ! git diff --cached --quiet; then
      git commit --amend --no-edit;
      gitpu origin local_manifests y;
    fi;
  fi;

  # Detect and update MultiROM references
  if cddevmrom && git submodule update --init --remote &&
      git reset "$(git rev-list --max-parents=0 --abbrev-commit HEAD)" &&
      git add -N ./ && ! git diff-index --quiet HEAD --; then
    echo '';
    echo " Updating MultiROM references...";
    git add "${params}";
    if ! git diff --cached --quiet; then
      git commit --amend --no-edit;
      gitpu origin local_manifests y;
    fi;
  fi;

  # Detect and update TWRP references
  if cddevtwrp && git submodule update --init --remote &&
      git reset "$(git rev-list --max-parents=0 --abbrev-commit HEAD)" &&
      git add -N ./ && ! git diff-index --quiet HEAD --; then
    echo '';
    echo " Updating TWRP references...";
    git add "${params}";
    if ! git diff --cached --quiet; then
      git commit --amend --no-edit;
      gitpu origin local_manifests y;
    fi;
  fi;

  # Path restore
  cd "${current_dir}";
}

# === Repo References Syncer ===
function reporefsync()
{
  # Usage: reporefsync [bool_dry_run] (Download new projects manifests)

  # Variables
  local current_dir;

  # Path backup
  current_dir=$(pwd);

  # Fetch and update AOSP references
  for project in sony8960_n sony8960_o sony8960_o_mr1 sony8960_master sonysodp aospcaf; do
    if cddevaosp "${project}"; then
      echo '';
      echo " Syncing AOSP ${project} references...";
      git fetch origin local_manifests;
      git --no-pager diff -R FETCH_HEAD;
      if [ -z "${1}" ]; then
        git reset FETCH_HEAD;
        git stash -u;
      fi;
      git submodule update --init --remote;
    fi;
  done;

  # Fetch and update LineageOS references
  for project in sony8960 sony8960_master sony8996 sonysodp; do
    if cddevlineage "${project}"; then
      echo '';
      echo " Syncing LineageOS ${project} references...";
      git fetch origin local_manifests;
      git --no-pager diff -R FETCH_HEAD;
      if [ -z "${1}" ]; then
        git reset FETCH_HEAD;
        git stash -u;
      fi;
      git submodule update --init --remote;
    fi;
  done;

  # Fetch and update common manifests references
  if cddev 'android_development_manifests'; then
    echo '';
    echo " Syncing common manifests references...";
    git fetch origin local_manifests;
    git --no-pager diff -R FETCH_HEAD;
    if [ -z "${1}" ]; then
      git reset FETCH_HEAD;
      git stash -u;
    fi;
    git submodule update --init --remote;
  fi;

  # Fetch and update MultiROM references
  if cddevmrom; then
    echo '';
    echo " Syncing MultiROM references...";
    git fetch origin local_manifests;
    git --no-pager diff -R FETCH_HEAD;
    if [ -z "${1}" ]; then
      git reset FETCH_HEAD;
      git stash -u;
    fi;
    git submodule update --init --remote;
  fi;

  # Fetch and update TWRP references
  if cddevtwrp; then
    echo '';
    echo " Syncing TWRP references...";
    git fetch origin local_manifests;
    git --no-pager diff -R FETCH_HEAD;
    if [ -z "${1}" ]; then
      git reset FETCH_HEAD;
      git stash -u;
    fi;
    git submodule update --init --remote;
  fi;

  # Path restore
  cd "${current_dir}";
  echo '';
}

# === Repo References Refresher ===
function reporefrefresh()
{
  # Usage: reporefrefresh (Download and upload new projects manifests)

  # Download and upload new projects manifests
  reporefsync '';
  reporefupdate true;
}

# === Repo Referenced Linker ===
function reporeflinker()
{
  # Usage: reporeflinker (Helper to symlink local_manifests to Developments)

  # Variables
  local cnt;
  local dev_path;
  local key;
  local local_manifests_file;
  local local_manifests_folder='';
  local options;
  local path;
  local project;
  local search_file;
  local search_project;
  local target;
  local untracked_file='';
  local untracked_project='';

  # Development path
  dev_path=$(getand)/Development;
  path=$(pwd);

  # Access local_manifests
  croot;
  cd ./.repo/local_manifests/;
  echo '';

  # Handle local_manifests files to link
  for file in roomservice.xml untracked.xml; do

    # Ignore actual files and not symlinks
    if [ -f "${file}" ] && [ ! -L "${file}" ]; then
      echo " reporeflinker: '${file}' already exists, ignoring.";
      continue;
    fi;

    # Delete remaining symlinks
    rm -f ./${file};

    # Reset inputs
    key='';
    search_project='';

    # Search for untracked detected project
    if [ "${file}" = 'untracked.xml' ] && [ ! -z "${untracked_project}" ]; then
      search_project=${untracked_project};
    fi;

    # Disabled file search
    if [ "${search_project}" = 'None' ]; then
      key=0;
    fi;

    # Create projects selector list
    cnt=0;
    options=('None');
    project=;
    echo '';
    echo -e " \e[1;37m[ Select a project for '${file}' ]\e[0m";
    echo '';
    echo "   ${cnt}: ${options[${cnt}]}";
    for project in ${dev_path}/*; do
      cnt=$((cnt + 1));
      options[${cnt}]=${project##*/};
      if [ "${options[${cnt}]}" = "${search_project}" ]; then
        key=${cnt};
      fi;
      echo "   ${cnt}: ${options[${cnt}]}";
    done;
    echo '';
    echo -en  " \e[1;33mProject to use [0 to ${cnt}] :\e[0m ";

    # Retrieve user input
    if [ -z "${key}" ]; then
      read -r key;
    else
      echo "${key}";
    fi;
    echo '';
    if [ "${key}" -gt 0 ] && [ "${key}" -le ${cnt} ]; then
      project=${options[${key}]};
    else
      project=;
    fi;

    # If project provided
    if [ ! -z "${project}" ]; then

      # Reset inputs
      key='';
      search_file='';

      # Search for untracked detected file
      if [ "${file}" = 'untracked.xml' ] && [ ! -z "${untracked_file}" ]; then
        search_file=${untracked_file};
      fi;

      # Create targets selector list
      cnt=0;
      options=('None');
      echo '';
      echo -e " \e[1;37m[ Select manifest target for '${file}' ]\e[0m";
      echo '';
      echo "   ${cnt}: ${options[${cnt}]}";
      for target in ${dev_path}/${project}/*.xml; do
        if [[ "${file}" == 'roomservice.xml' && "${target##*/}" == 'untracked-'* ]] ||
            [[ "${file}" == 'untracked.xml' && ! "${target##*/}" == 'untracked-'* ]]; then
          continue;
        fi;
        cnt=$((cnt + 1));
        options[${cnt}]=${target##*/};
        if [ "${options[${cnt}]}" = "${search_file}.xml" ]; then
          key=${cnt};
        fi;
        echo "   ${cnt}: ${options[${cnt}]}";
      done;
      echo '';
      echo -en  " \e[1;33mmanifest target to use [0 to ${cnt}] :\e[0m ";

      # Force default file if only one choice available
      if [ "${cnt}" -eq 1 ]; then
        key=1;
      fi;

      # Retrieve user input
      if [ -z "${key}" ]; then
        read -r key;
      else
        echo "${key}";
      fi;
      echo '';
      if [ "${key}" -gt 0 ] && [ "${key}" -le ${cnt} ]; then
        target=${options[${key}]};

        # Generate symlink to file
        echo -n ' ';
        ln -fsv "${dev_path}/${project}/${target}" "./${file}";
        echo '';

        # Handle roomservice custom configurations
        if [ "${file}" = 'roomservice.xml' ]; then

          # Detect local_manifests projects from roomservice
          local_manifests_folder=$(grep "Local Manifests: '" "${file}" | sed "s/.* '\(.*\)' .*/\1/");
          if [ ! -z "${local_manifests_folder}" ] && [ -d "${dev_path}/${project}/${local_manifests_folder}" ]; then

            # Link local_manifests projects
            echo '';
            echo -e  " \e[1;32mDetected local_manifests to use : '${local_manifests_folder}' in '${project}'\e[0m ";
            echo '';
            for local_manifests_file in "${dev_path}/${project}/${local_manifests_folder}/"*; do
              ln -fsv "${local_manifests_file}" "./${local_manifests_file##*/}";
            done;

          fi;

          # Detect untracked tags from roomservice
          untracked_file=$(grep "Untracked: '" "${file}" | sed "s/.* '\(.*\)' .*/\1/");
          if grep -q "Untracked: '" "${file}"; then

            # Extract untracked tags
            untracked_project=${untracked_file%/*};
            untracked_file=${untracked_file#*/};
            echo '';
            echo -e  " \e[1;32mDetected untracked.xml to use : '${untracked_file}' in '${untracked_project}'\e[0m ";
            echo '';

            # Disable empty untracked tags
            if [ -z "${untracked_file}" ] && [ -z "${untracked_project}" ]; then
              untracked_project='None';
            fi;

          fi;

        fi;

      fi;
    fi;
  done;

  # Return to current path
  cd "${path}";
  echo '';
}
